package com.ldf;

import com.aizuda.zlm4j.callback.IMKCloseEventCallBack;
import com.aizuda.zlm4j.core.ZLMApi;
import com.aizuda.zlm4j.structure.CodecArgs;
import com.aizuda.zlm4j.structure.MK_INI;
import com.aizuda.zlm4j.structure.MK_MEDIA;
import com.aizuda.zlm4j.structure.MK_TRACK;
import com.ldf.callback.FRealDataCallback;
import com.ldf.core.HCNetSDK;
import com.sun.jna.Native;
import com.sun.jna.Pointer;

/**
 * 实时播放Demo
 *
 * @author lidaofu
 * @since 2023/12/1
 **/
public class RealPlayDemo {
    public static ZLMApi ZLM_API = Native.load("mk_api", ZLMApi.class);
    public static HCNetSDK hCNetSDK = Native.load("HCNetSDK", HCNetSDK.class);
    static int lUserID = 0;

    public static void main(String[] args) throws InterruptedException {
        //初始化zmk服务器
        ZLM_API.mk_env_init1(1, 1, 1, null, 0, 0, null, 0, null, null);
        //创建http服务器 0:失败,非0:端口号
        short http_server_port = ZLM_API.mk_http_server_start((short) 7788, 0);
        //创建rtsp服务器 0:失败,非0:端口号
        short rtsp_server_port = ZLM_API.mk_rtsp_server_start((short) 7554, 0);
        //创建rtmp服务器 0:失败,非0:端口号
        short rtmp_server_port = ZLM_API.mk_rtmp_server_start((short) 7935, 0);
        //初始化海康SDK
        boolean initSuc = hCNetSDK.NET_DVR_Init();
        if (!initSuc) {
            System.out.println("海康SDK初始化失败");
            return;
        }
        //登录海康设备
        Login_V40("192.168.1.64", (short) 8000, "admin", "hk123456");
        MK_INI mkIni = ZLM_API.mk_ini_create();
        ZLM_API.mk_ini_set_option(mkIni, "enable_rtsp", "1");
        ZLM_API.mk_ini_set_option(mkIni, "enable_rtmp", "1");
        ZLM_API.mk_ini_set_option_int(mkIni, "auto_close", 1);
        //创建媒体
        MK_MEDIA mkMedia = ZLM_API.mk_media_create2("__defaultVhost__", "live", "test", 0, mkIni);
        ZLM_API.mk_ini_release(mkIni);
        //这里分辨率、帧率、码率都可随便写 0是H264 1是h265 可以事先定义好 也可以放到回调里面判断编码类型让后再初始化这个
        ZLM_API.mk_media_init_video(mkMedia, 0, 1, 1, 25.0f, 2500);
        ZLM_API.mk_media_init_audio(mkMedia, 2, 8000, 1, 16);
        ZLM_API.mk_media_init_complete(mkMedia);
        FRealDataCallback fRealDataCallBack = new FRealDataCallback(mkMedia, 25.0);
        HCNetSDK.NET_DVR_PREVIEWINFO netDvrPreviewinfo = new HCNetSDK.NET_DVR_PREVIEWINFO();
        netDvrPreviewinfo.lChannel = 1;
        netDvrPreviewinfo.dwStreamType = 0;
        netDvrPreviewinfo.bBlocked = 0;
        netDvrPreviewinfo.dwLinkMode = 0;
        netDvrPreviewinfo.byProtoType = 0;
        //播放视频
        long ret = hCNetSDK.NET_DVR_RealPlay_V40(lUserID, netDvrPreviewinfo, fRealDataCallBack, Pointer.NULL);
        if (ret == -1) {
            System.out.println("【海康SDK】开始sdk播放视频失败! 错误码：" + hCNetSDK.NET_DVR_GetLastError());
            return;
        }
        ZLM_API.mk_media_set_on_close(mkMedia, pointer -> {
            fRealDataCallBack.release();
            hCNetSDK.NET_DVR_StopRealPlay(ret);
            System.out.println("流关闭自动释放资源");
        }, Pointer.NULL);
        //休眠
        Thread.sleep(120000);
       // fRealDataCallBack.release();
        // hCNetSDK.NET_DVR_StopRealPlay(ret);
        Logout();
    }

    /**
     * 登录
     *
     * @param m_sDeviceIP 设备ip地址
     * @param wPort       端口号，设备网络SDK登录默认端口8000
     * @param m_sUsername 用户名
     * @param m_sPassword 密码
     */
    public static void Login_V40(String m_sDeviceIP, short wPort, String m_sUsername, String m_sPassword) {
        /* 注册 */
        // 设备登录信息
        HCNetSDK.NET_DVR_USER_LOGIN_INFO m_strLoginInfo = new HCNetSDK.NET_DVR_USER_LOGIN_INFO();
        // 设备信息
        HCNetSDK.NET_DVR_DEVICEINFO_V40 m_strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V40();
        m_strLoginInfo.sDeviceAddress = new byte[HCNetSDK.NET_DVR_DEV_ADDRESS_MAX_LEN];
        System.arraycopy(m_sDeviceIP.getBytes(), 0, m_strLoginInfo.sDeviceAddress, 0, m_sDeviceIP.length());
        m_strLoginInfo.wPort = wPort;
        m_strLoginInfo.sUserName = new byte[HCNetSDK.NET_DVR_LOGIN_USERNAME_MAX_LEN];
        System.arraycopy(m_sUsername.getBytes(), 0, m_strLoginInfo.sUserName, 0, m_sUsername.length());
        m_strLoginInfo.sPassword = new byte[HCNetSDK.NET_DVR_LOGIN_PASSWD_MAX_LEN];
        System.arraycopy(m_sPassword.getBytes(), 0, m_strLoginInfo.sPassword, 0, m_sPassword.length());
        // 是否异步登录：false- 否，true- 是
        m_strLoginInfo.bUseAsynLogin = false;
        // write()调用后数据才写入到内存中
        m_strLoginInfo.write();

        lUserID = hCNetSDK.NET_DVR_Login_V40(m_strLoginInfo, m_strDeviceInfo);
        if (lUserID == -1) {
            System.out.println("登录失败，错误码为" + hCNetSDK.NET_DVR_GetLastError());
            return;
        } else {
            System.out.println("登录成功！");

            // read()后，结构体中才有对应的数据
            m_strDeviceInfo.read();
            return;
        }
    }

    //设备注销 SDK释放
    public static void Logout() {
        if (lUserID >= 0) {
            if (!hCNetSDK.NET_DVR_Logout(lUserID)) {
                System.out.println("注销失败，错误码为" + hCNetSDK.NET_DVR_GetLastError());
            }
            System.out.println("注销成功");
            hCNetSDK.NET_DVR_Cleanup();
            return;
        } else {
            System.out.println("设备未登录");
            hCNetSDK.NET_DVR_Cleanup();
            return;
        }
    }
}
